﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Client.Forms;
using MahApps.Metro.Controls.Dialogs;
using Managers;
using Managers.LiveControl.Client;
using Managers.Nova.Client;
using Microsoft.Win32;
using Model.Nova;
using Network;
using Network.Messages.Nova;
using Providers.Nova.Client;
using Providers.Nova.Modules;
using Wpf_Client.Properties;
using Wpf_Client.ViewModel;

namespace Wpf_Client
{
    /// <summary>
    ///     MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow
    {
        private readonly string _currentExeName;

        private readonly Dictionary<string, string> _dicUserPasswords = new Dictionary<string, string>();
        private readonly MainWindowViewModel _viewModel;
        private string _serverName;
        
        public MainWindow()
        {
            _viewModel = new MainWindowViewModel(DialogCoordinator.Instance);
            DataContext = _viewModel;

            InitializeComponent();
            _currentExeName = Assembly.GetEntryAssembly().GetName().Name;
            Loaded += MainWindow_Loaded;
       
        }

        public NovaManager NovaManager => NovaClient.Instance.NovaManager;
        private async void NovaManager_OnNoManOnDutyRegistrationCompletedEvent(object sender,
            NoManOnDutyRegistStatusArgs e)
        {
            switch (e.Result)
            {
                case MachineLookupTable.Status.Successed:
                    await this.ShowMessageAsync("注册成功", "成功注册无人值守验证信息，其它机器可通过该验证信息控制当前机器。");
                    break;
                case MachineLookupTable.Status.RegistedByOtherMachine:
                    await this.ShowMessageAsync("注册失败", "该用户名已在其它机器被注册，请更换用户名。");
                    break;
                case MachineLookupTable.Status.Failed:
                    await this.ShowMessageAsync("注册失败", "无法连接服务器数据库。");
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private double _connectTime;
        private async void ClientManager_OnIntroductionCompleted(object sender,
            IntroducerIntroductionCompletedEventArgs e)
        {
            switch (e.Result)
            {
                case ResponseIntroducerIntroductionCompletedMessage.Result.Denied:
                    string reason;
                    switch (e.DenyReason)
                    {
                        case ResponseIntroducerIntroductionCompletedMessage.Reason.WrongPassword:
                            reason = "密码错误";
                            break;
                        case ResponseIntroducerIntroductionCompletedMessage.Reason.Banned:
                            reason = "账户被禁用";
                            break;
                        case ResponseIntroducerIntroductionCompletedMessage.Reason.IdNotFound:
                            reason = $"您所输入的ID {_viewModel.TargetServerModel.TargetId}不存在";
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                    await this.ShowMessageAsync("连接失败", $"失败原因: {reason}");
                    break;
                case ResponseIntroducerIntroductionCompletedMessage.Result.Allowed:
                    double timeDelay = 3;
                    _connectTime = NovaManager.Now + timeDelay;

                    _viewModel.AddHisServer();
                    CboxTargetId.ItemsSource = _viewModel.TargetServerList;

                    await Delay(timeDelay*1000);
                    if (!_connect&& NovaManager.Now>= _connectTime)
                    {
                        await this.ShowMessageAsync("连接失败", $"目标机器:({_viewModel.TargetServerModel.TargetId})可能并未开启服务端，或者本地机器与目标机器间连接信息被防火墙阻挡。");
                    }
                  
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private bool _connect = false;
        public static Task Delay(double milliseconds)
        {
            var tcs = new TaskCompletionSource<bool>();
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Elapsed += (obj, args) =>
            {
                tcs.TrySetResult(true);
            };
            timer.Interval = milliseconds;
            timer.AutoReset = false;
            timer.Start();
            return tcs.Task;
        }
        private void ClientManager_OnConnected(object sender, ConnectedEventArgs e)
        {
            var tLiveControl = new FormLiveControl();
            tLiveControl.Closed += TLiveControl_Closed;
            tLiveControl.Show();
            _connect = true;

        }

        private async void TLiveControl_Closed(object sender, EventArgs e)
        {
            FormLiveControl tLiveControl = (FormLiveControl) sender;
            tLiveControl.Closed -= TLiveControl_Closed;
            switch (tLiveControl.CloseType)
            {
                case CloseType.ServerClose:
                    await this.ShowMessageAsync("目标机器服务端被关闭", $"目标机器:({_viewModel.TargetServerModel.TargetId})服务端被关闭，或者电脑被重启。");

                    break;
                case CloseType.Disconnect:
                    await this.ShowMessageAsync("网络断开", $"目标机器:({_viewModel.TargetServerModel.TargetId})网络断开导致无法连接，请检查。");

                    break;
                case CloseType.UserClose:

                    break;
                case CloseType.ShareFormClose:
                    await this.ShowMessageAsync("目标窗口被关闭", $"共享的单窗被关闭，如需重新连接，请使用全屏模式将其打开。");

                    break;
                case CloseType.ShareFormMiniSize:
                    await this.ShowMessageAsync("目标窗口被最小化", $"共享的单窗被最小化，重新连接时会自动恢复它的显示状态。");
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void ClientManager_OnNatTraversalSucceeded(object sender, NatTraversedEventArgs e)
        {
            //throw new NotImplementedException();
        }

        private bool _flagServerOpened = false;

        private void NovaManager_OnSeverInfoRecived(object sender, SeverInfoArgs e)
        {
            _viewModel.LocalServerModel.TargetId = e.Novaid;
            _viewModel.LocalServerModel.TargetPassword = e.Password;
            _viewModel.About.Id = e.Novaid;
        }


        private async void StartSever(string serverName)
        {
            await Task.Factory.StartNew(() =>
            {
                try
                {
                    //1、判断服务器是否打开
                    if (Process.GetProcessesByName(serverName).Length <= 0)
                    {
                        //2、没打开就请求打开
                        Process.Start(AppDomain.CurrentDomain.BaseDirectory + $"{serverName}.exe");
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            });
            NovaManager.StartKeepConnectToServer(200);
            NovaManager.RequestServerInfo();
        }

        private void KillSever(string serverName)
        {
            Process[] processes = Process.GetProcessesByName(serverName);
            foreach (Process p in processes.Where(p => p.ProcessName == serverName))
            {
                //p.CloseMainWindow();
                //这货的窗口被我隐藏了，没法通过窗口消息的方式通知到，只能用暴力的方式了。
                p.Kill();
                p.Close();
            }
        }

        private void NovaManager_OnServerStatusChanged(object sender, ServerAliveStatusArgs e)
        {
            if (e.FlagAlive)
            {
                Action<Button, String> updateAction = UpdateBtn;
                BtnServerControl.Dispatcher.BeginInvoke(updateAction, BtnServerControl, "关闭服务");

                _flagServerOpened = true;
            }
            else
            {
                Action<Button, String> updateAction = UpdateBtn;
                BtnServerControl.Dispatcher.BeginInvoke(updateAction, BtnServerControl, "打开服务");
                _viewModel.LocalServerModel.TargetId = "-";
                _viewModel.LocalServerModel.TargetPassword = "-";
                _viewModel.About.Id = "";
                _flagServerOpened = false;
            }
        }

        private void UpdateBtn(Button btn, string content)
        {
            btn.Content = content;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            NovaManager.OnSeverInfoRecived += NovaManager_OnSeverInfoRecived;
            NovaManager.OnNatTraversalSucceeded += ClientManager_OnNatTraversalSucceeded;
            NovaManager.OnConnected += ClientManager_OnConnected;
            NovaManager.OnIntroductionCompleted += ClientManager_OnIntroductionCompleted;
            NovaManager.OnNoManOnDutyRegistrationCompletedEvent += NovaManager_OnNoManOnDutyRegistrationCompletedEvent;
            NovaManager.OnServerStatusChanged += NovaManager_OnServerStatusChanged;
            _serverName = Settings.Default.ServerExeName;

            CboxEasyAccess.IsChecked = IsStartWithWindow(_serverName);
            CboxStartWithWindows.IsChecked = IsStartWithWindow(_currentExeName);
            _viewModel.LoadColor();
            CboxTargetId.ItemsSource = _viewModel.TargetServerList;
            _viewModel.ShowMyTitleBar = false;
            StartSever(_serverName);

            //ShowWpfWindow();
        }

    

        private void Grid_MouseMove(object sender, MouseEventArgs e)
        {
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            var password = "";
            _dicUserPasswords.TryGetValue(_viewModel.TargetServerModel.TargetId, out password);
            var result = await this.ShowLoginAsync("验证", "请输入伙伴计算上显示的密码", new LoginDialogSettings
            {
                ColorScheme = MetroDialogOptions.ColorScheme, ShouldHideUsername = true, PasswordWatermark = "密码", InitialPassword = password, AffirmativeButtonText = "登陆", NegativeButtonVisibility = Visibility.Visible, EnablePasswordPreview = string.IsNullOrEmpty(password), NegativeButtonText = "取消"
            });
            if (result != null)
            {
                // 将连接状态重置
                _connect = false;
                await NovaManager.RequestIntroductionAsTask(_viewModel.TargetServerModel.TargetId, result.Password);
                _dicUserPasswords[_viewModel.TargetServerModel.TargetId] = result.Password;
            }
        }

        private async void SetterMenuItemClick(object sender, RoutedEventArgs e)
        {
            var result = await this.ShowLoginAsync("设置无人值守验证信息", "请输入用于无人值守时使用的验证信息，注册后使用该验证信息可以直接连当前机器，而不用知道对方的临时账号和随机密码。", new LoginDialogSettings
            {
                ColorScheme = MetroDialogOptions.ColorScheme, ShouldHideUsername = false, PasswordWatermark = "密码", UsernameWatermark = "计算机名", AffirmativeButtonText = "确认", NegativeButtonVisibility = Visibility.Visible, EnablePasswordPreview = true, NegativeButtonText = "取消"
            });
            if (result != null)
            {
                await NovaManager.RegisterNoManOnDutyAsTask(result.Username, result.Password);
            }
        }

        private void MetroWindow_Closing(object sender, CancelEventArgs e)
        {
            NovaManager.StopTimer();
            NovaManager.Network.Shutdown();
        }

        private void BtnRefreshPassword_Click(object sender, RoutedEventArgs e)
        {
            NovaManager.RequestNewPassword();
        }

        private void UpdateSever_OnClick(object sender, RoutedEventArgs e)
        {
            //throw new NotImplementedException();
        }

        /// <summary>
        ///     修改程序在注册表中的键值
        /// </summary>
        /// <param name="flag">1:开机启动</param>
        /// <param name="exeName">需要开机启动的exe名称</param>
        private async void StartUp(string flag, string exeName)
        {
            await Task.Factory.StartNew(() =>
            {
                var path = AppDomain.CurrentDomain.BaseDirectory;
                var keyName = exeName;
                var rkey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);

                if (flag.Equals("1"))
                {
                    if (rkey == null)
                    {
                        rkey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    rkey?.SetValue(keyName, path + $"{exeName}.exe");
                }
                else
                {
                    rkey?.DeleteValue(keyName, false);
                }
            });
        }

        private bool IsStartWithWindow(string exeName)
        {
            var keyName = exeName;
            var rkey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);

            var value = rkey?.GetValue(keyName);
            return value != null;
        }

        private void EasyAccessCheckBoxChecked(object sender, RoutedEventArgs e)
        {
            StartUp("1", _serverName);
        }

        private void EasyAccessCheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            StartUp("0", _serverName);
        }

        private void StartWithWindowsCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            StartUp("1", _currentExeName);
            CboxEasyAccess.IsChecked = true;
        }

        private void StartWithWindowsCheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            StartUp("0", _currentExeName);
            CboxEasyAccess.IsChecked = IsStartWithWindow(_serverName);
        }

        private void BtnServerControl_OnClick(object sender, RoutedEventArgs e)
        {
            if (_flagServerOpened)
            {
                //KillSever(_serverName);
                NovaManager.AskServerShutdown();
            }
            else
            {
                StartSever(_serverName);
            }
        }
    }
}